<?php

/**
 * Framework_File
 *
 * @author      Ian Szewczyk <roamzero@gmail.com>
 * @copyright   (c) 2007 Ian Szewczyk. All rights reserved.
 * @license     http://www.opensource.org/licenses/bsd-license.php
 * @package Framework
 * @filesource
 */

/**
 * Framework_File
 *
 *
 * @author Ian Szewczyk <roamzero@gmail.com>
 * @package Framework
 * @todo Make 'File' an individual file class and make a separate file manager class
 */
class Framework_File extends Framework_Object_DB
{
	/**
	 * $owner
	 *
	 * @access      private
	 * @var         Framework_Owner      $owner
	 */
	private $owner;

	/**
	 * $imageTypes
	 *
	 * @access      private
	 * @var         array      $imageTypes
	 */
	private $imageTypes = array(
		'image/gif',   // Opera, Moz, MSIE
		'image/jpeg',  // Opera, Moz
		'image/png',   // Opera, Moz
		'image/pjpeg', // MSIE
		'image/x-png'  // MSIE
	);
	
	/**
	 * $textTypes
	 *
	 * @access      private
	 * @var         array      $textTypes
	 */
	private $textTypes = array(
		'text/plain',
		'text/css'
	);

	/**
	 * __construct
	 *
	 *
	 * @access      public
	 * @param		Framework_Owner		$owner
	 * @return      void
	 */
	public function __construct($owner = null)
	{
		parent::__construct();
		$this->owner = $owner;
	}

	/**
	 * addFileUpload
	 *
	 *
	 * @access      public
	 * @param		object		$file			File object from QuickForm
	 * @param		string		$folder			Folder to save the file under in Uploads
	 * @param		string		$filename		The desired filename (minus extension)
	 * @return      mixed		array fileinfo on succes, PEAR::error on failure
	 * 
	 */
	public function addFileUpload($file, $folder, $fileName = null)
	{
		
		$fileInfo = $file->getValue();

		// This is where the full type validation would take place
		if(in_array($fileInfo['type'],$this->imageTypes)) {
			if(extension_loaded("exif") && !exif_imagetype($fileInfo['tmp_name']))
			return PEAR::raiseError('Invalid Image');
		} elseif (in_array($fileInfo['type'],$this->textTypes)) {
			$fp = fopen($fileInfo['tmp_name'], 'r');
			$data = fread($fp, filesize($fileInfo['tmp_name']));
			//$data = $this->util->filter_removeXSS($data);
			$data = str_replace('<?',' ',$data);
			$isText = true;
			fclose($fp);
		} else {
			return PEAR::raiseError('Invalid File');
		}
		
		$queryArray = array(
			'sqlKey' => 'getFileExtensionForUploaded',
			'params' => $fileInfo['type']
		);
		
		$ext = $this->owner->select($queryArray);


		$md5 = md5_file($fileInfo['tmp_name']);
		$path = '/uploads/'.$folder.'/'.$md5{1}.'/'.$md5{1}.$md5{2};
		$dir = dirname($_SERVER['SCRIPT_FILENAME']).$path;
		if (!file_exists($dir)) {
			$this->recursiveMkdir($dir); //mkdir($dir, 0777, true);
		}
		
		$ownerFileTable = $this->owner->getTable('OwnerFile');

		$fileID = $ownerFileTable->nextID();

		if (!$fileName) {
			$fileName = $fileID;
		}
		
		$ownerFileTable->idOwnerFile = $fileID;
		$ownerFileTable->idFileMeta = $ext['idFileMeta'];
		$ownerFileTable->idOwner = $this->owner->idOwner;
		$ownerFileTable->fileName = $fileName;
		$ownerFileTable->filePointer = $path;
		$ownerFileTable->folder = $folder;
		$queryResult = $ownerFileTable->save();
		

		// Again, result should be changed to an object
		$result['httpPath'] = Framework::$request->getBaseHTTPPath(false).$path.'/'.$fileName.'.'.$ext['extension'];
		$result['fullPath'] = $dir.'/'.$fileName.'.'.$ext['extension'];
		$result['path'] = $path.'/'.$fileName.'.'.$ext['extension'];
		$result['dir'] = $dir;
		$result['fileName'] = $fileName;
		$result['ext'] = $ext['extension'];
		$result['hashPath'] = $md5{1}.'/'.$md5{1}.$md5{2}.'/';
		$result['fileID'] = $fileID;

		

		if($isText) {
			$fp = fopen($dir.'/'.$fileName.'.'.$ext['extension'], 'w');
			fwrite($fp, $data);
			fclose($fp);
		} else {
			$file->moveUploadedFile($dir,$fileName.'.'.$ext['extension']);
			chmod($result['fullPath'], 0644);
		}
		if (PEAR::isError($queryResult)) {
			return PEAR::raiseError('Database Error: Could not store file information in the database: '.$queryResult->getMessage());
		} else {
			return $result;
		}

	}

	/**
	 * removeFile
	 *
	 *
	 * @access      public
	 * @param		string		$folder			Folder that the file resides in under Uploads
	 * @param		string		$name			Name of the file (minus extension)
	 * @param		integer		$id				The id of the file, used if missing file name and folder
	 * @return      mixed		array fileinfo on succes, PEAR::error on failure
	 * 
	 */
	public function removeFile($folder = null, $name = null, $id = null)
	{
		

		$result = $this->getFile($folder, $name, $id);
		if(PEAR::isError($result) || !is_array($result))
			return PEAR::raiseError('Database Error: Either file not found in the database or database cannot be reached');
		else
			$delete = @unlink($result['filePath']);

		if(!delete)
		return PEAR::raiseError('File Error: Could not remove file');
		
		$result = $this->owner->delete('OwnerFile', 'idOwnerFile = '.$result['idOwnerFile'] );

		if(PEAR::isError($result))
			return PEAR::raiseError('Database Error: Could not remove file information from the database');
		else
			return true;
	}
	
	/**
	 * getFile
	 *
	 *
	 * @access      public
	 * @param		string		$folder			Folder that the file resides in under Uploads
	 * @param		string		$name			Name of the file (minus extension)
	 * @param		integer		$id				The id of the file, used if missing file name and folder
	 * @return      mixed		array fileinfo on succes, PEAR::error on failure
	 * 
	 */
	public function getFile($folder = null, $name = null, $id = null)
	{
		if ($id) {
			$queryArray = array(
				'sqlKey' => 'getFileByID',
				'params' => array($id)
			);
		} else {
			$queryArray = array(
				'sqlKey' => 'getFileByFileName',
				'params' => array($folder, $name, $this->owner->idOwner)
			);
		}
		
		$result = $this->owner->select($queryArray);
		
		if (!PEAR::isError($result) && count($result)) {
			$result['httpPath'] = Framework::$request->getBaseHTTPPath(false).$result['filePointer'].'/'.$result['fileName'].'.'.$result['extension'];
			$result['filePath'] = dirname($_SERVER['SCRIPT_FILENAME']).$result['filePointer'].'/'.$result['fileName'].'.'.$result['extension'];
		}
		
		return $result;
	}


	/**
	 * recursiveMkdir
	 *
	 *
	 * @access      private
	 * @param		string		$path		Path
	 * @return		void 
	 */
	private function recursiveMkdir($path)
	{
		// This function creates the specified directory using mkdir().  Note
		// that the recursive feature on mkdir() is broken with PHP 5.0.4 for
		// Windows, so I have to do the recursion myself.
		if (!file_exists($path))
		{
			// The directory doesn't exist.  Recurse, passing in the parent
			// directory so that it gets created.
			$this->RecursiveMkdir(dirname($path));

			mkdir($path, 0777);
		}
	}


}

?>